#include <gtest/gtest.h>
#include <memory>
#include <cmath>
#include "base/context_builder/context_holder.h"
#include "base/context_builder/op_info.h"
#include "base/context_builder/op_kernel_run_context_builder.h"
#include "base/context_builder/op_infer_datatype_context_builder.h"
#include "base/context_builder/op_infer_shape_context_builder.h"
#include "base/context_builder/op_infer_shape_range_context_builder.h"
#include "base/context_builder/op_tiling_context_builder.h"
#include "base/context_builder/op_tiling_parse_context_builder.h"
#include "graph/def_types.h"
#include "exe_graph/runtime/kernel_run_context.h"
#include "exe_graph/runtime/extended_kernel_context.h"
#include "exe_graph/runtime/kernel_context.h"
#include "exe_graph/runtime/infer_datatype_context.h"
#include "exe_graph/runtime/infer_shape_context.h"
#include "exe_graph/runtime/infer_shape_range_context.h"
#include "exe_graph/runtime/tiling_context.h"
#include "exe_graph/runtime/tiling_parse_context.h"

using namespace gert;
using namespace ge;
class UtestContextBuilder : public testing::Test {};

TEST_F(UtestContextBuilder, CreateKernelRunContextOK) {
  OpKernelRunContextBuilder ctx_builder;
  gert::StorageShape shape0 = {{10, 20}, {10, 20}};
  ctx_builder.MutableOpInfo()
      .OpType("Add")
      .OpName("add_1")
      .IONum(2, 1)
      .SetInputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ)
      .SetInputTd(1, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ)
      .SetOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ);
  auto holder = ctx_builder.Inputs({&shape0, &shape0}).Outputs({&shape0}).Build();
  auto ctx = (KernelContext *) holder.GetContext();
  EXPECT_NE(ctx, nullptr);
  auto ctx_compute_node_info = (gert::ComputeNodeInfo *) (ctx->GetComputeNodeExtend());
  EXPECT_NE(ctx_compute_node_info, nullptr);
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeType()), std::string("Add"));
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeName()), std::string("add_1"));
  EXPECT_EQ(ctx_compute_node_info->GetIrInputsNum(), 2);
  EXPECT_EQ(ctx_compute_node_info->GetIrOutputsNum(), 1);
  EXPECT_EQ(ctx_compute_node_info->GetInputsNum(), 2);
  EXPECT_EQ(ctx_compute_node_info->GetOutputsNum(), 1);
  const CompileTimeTensorDesc *info_input_0 = ctx_compute_node_info->GetInputTdInfo(0);
  EXPECT_NE(info_input_0, nullptr);
  EXPECT_EQ(info_input_0->GetStorageFormat(), ge::FORMAT_FRACTAL_NZ);
  EXPECT_EQ(info_input_0->GetOriginFormat(), ge::FORMAT_ND);
  EXPECT_EQ(ctx->GetInput(0)->GetPointer<gert::StorageShape>(), &shape0);
  EXPECT_EQ(ctx->GetInput(1)->GetPointer<gert::StorageShape>(), &shape0);
  EXPECT_EQ(ctx->GetOutput(0)->GetPointer<gert::StorageShape>(), &shape0);
}

TEST_F(UtestContextBuilder, CreateKernelRunContextFailed) {
  OpKernelRunContextBuilder ctx_builder;
  gert::StorageShape shape0 = {{10, 20}, {10, 20}};
  ctx_builder.MutableOpInfo()
      .OpName("add_1")
      .IONum(1, 1)
      .SetInputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ)
      .SetInputTd(1, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ)
      .SetOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ);
  auto holder = ctx_builder.Inputs({&shape0, &shape0}).Outputs({&shape0}).Build();
  auto ctx = (KernelContext *) holder.GetContext();
  EXPECT_EQ(ctx, nullptr);
}

TEST_F(UtestContextBuilder, CreateInferDataTypeContextOK) {
  OpInferDataTypeContextBuilder ctx_builder;
  ge::DataType dtype0 = ge::DT_FLOAT;
  ge::DataType dtype1 = ge::DT_FLOAT16;
  ge::DataType dtype2 = ge::DT_FLOAT;
  ge::DataType dtype3 = ge::DT_FLOAT16;
  ge::DataType dtype4 = ge::DT_FLOAT16;

  std::vector<ge::DataType *> input_dtype_ref = {&dtype0, &dtype1, &dtype2, &dtype3};
  std::vector<ge::DataType *> output_dtype_ref = {&dtype4};
  ctx_builder.MutableOpInfo()
      .OpType("Concat")
      .OpName("concat_1")
      .IOInstanceNum({4}, {1})
      .SetInputTd(0, dtype0, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(1, dtype1, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(2, dtype2, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(3, dtype3, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetOutputTd(0, ge::DT_FLOAT, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND);
  auto holder = ctx_builder.Inputs(input_dtype_ref).Outputs(output_dtype_ref).Build();
  auto ctx = holder.GetContext();
  EXPECT_NE(ctx, nullptr);
  auto ctx_compute_node_info = ctx->GetComputeNodeInfo();
  EXPECT_NE(ctx_compute_node_info, nullptr);
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeType()), std::string("Concat"));
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeName()), std::string("concat_1"));
  EXPECT_EQ(ctx_compute_node_info->GetIrInputsNum(), 4);
  EXPECT_EQ(ctx_compute_node_info->GetIrOutputsNum(), 1);
  EXPECT_EQ(ctx_compute_node_info->GetInputsNum(), 1);
  EXPECT_EQ(ctx_compute_node_info->GetOutputsNum(), 1);
  const CompileTimeTensorDesc *info_input_0 = ctx_compute_node_info->GetInputTdInfo(0);
  EXPECT_NE(info_input_0, nullptr);
  EXPECT_EQ(info_input_0->GetStorageFormat(), ge::FORMAT_ND);
  EXPECT_EQ(info_input_0->GetOriginFormat(), ge::FORMAT_FRACTAL_NZ);
  ge::DataType expected_datatype_0 = ge::DT_FLOAT;
  ge::DataType expected_datatype_1 = ge::DT_FLOAT16;
  EXPECT_EQ(ctx->GetInputDataType(0), expected_datatype_0);
  EXPECT_EQ(ctx->GetInputDataType(1), expected_datatype_1);
  EXPECT_EQ(ctx->GetInputDataType(2), expected_datatype_0);
  EXPECT_EQ(ctx->GetInputDataType(3), expected_datatype_1);
  EXPECT_EQ(ctx->GetOutputDataType(0), expected_datatype_1);
}

TEST_F(UtestContextBuilder, CreateInferDataTypeWithTypeContextOK) {
  OpInferDataTypeContextBuilder ctx_builder;
  ge::DataType dtype0 = ge::DT_FLOAT;
  ge::DataType dtype1 = ge::DT_FLOAT16;
  ge::DataType dtype2 = ge::DT_FLOAT;
  ge::DataType dtype3 = ge::DT_FLOAT16;
  ge::DataType dtype4 = ge::DT_FLOAT16;

  std::vector<ge::DataType> input_dtype_ref = {dtype0, dtype1, dtype2, dtype3};
  std::vector<ge::DataType *> output_dtype_ref = {&dtype4};
  ctx_builder.MutableOpInfo()
      .OpType("Concat")
      .OpName("concat_1")
      .IOInstanceNum({4}, {1})
      .SetInputTd(0, dtype0, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(1, dtype1, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(2, dtype2, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(3, dtype3, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetOutputTd(0, ge::DT_FLOAT, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND);
  auto holder = ctx_builder.Inputs(input_dtype_ref).Outputs(output_dtype_ref).Build();
  auto ctx = holder.GetContext();
  EXPECT_NE(ctx, nullptr);
  auto ctx_compute_node_info = ctx->GetComputeNodeInfo();
  EXPECT_NE(ctx_compute_node_info, nullptr);
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeType()), std::string("Concat"));
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeName()), std::string("concat_1"));
  EXPECT_EQ(ctx_compute_node_info->GetIrInputsNum(), 4);
  EXPECT_EQ(ctx_compute_node_info->GetIrOutputsNum(), 1);
  EXPECT_EQ(ctx_compute_node_info->GetInputsNum(), 1);
  EXPECT_EQ(ctx_compute_node_info->GetOutputsNum(), 1);
  const CompileTimeTensorDesc *info_input_0 = ctx_compute_node_info->GetInputTdInfo(0);
  EXPECT_NE(info_input_0, nullptr);
  EXPECT_EQ(info_input_0->GetStorageFormat(), ge::FORMAT_ND);
  EXPECT_EQ(info_input_0->GetOriginFormat(), ge::FORMAT_FRACTAL_NZ);
  ge::DataType expected_datatype_0 = ge::DT_FLOAT;
  ge::DataType expected_datatype_1 = ge::DT_FLOAT16;
  EXPECT_EQ(ctx->GetInputDataType(0), expected_datatype_0);
  EXPECT_EQ(ctx->GetInputDataType(1), expected_datatype_1);
  EXPECT_EQ(ctx->GetInputDataType(2), expected_datatype_0);
  EXPECT_EQ(ctx->GetInputDataType(3), expected_datatype_1);
  EXPECT_EQ(ctx->GetOutputDataType(0), expected_datatype_1);
}

TEST_F(UtestContextBuilder, CreateInferShapeContextFailed) {
  OpInferShapeContextBuilder ctx_builder;
  gert::StorageShape shape0 = {{10, 20}, {10, 20}};
  ctx_builder.MutableOpInfo()
      .OpType("DIY")
      .OpName("diy_1")
      .IONum(2, 1)
      .SetInputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ)
      .SetInputTd(1, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ)
      .SetInputTd(2, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ)
      .SetOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ)
      .SetOutputTd(1, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ);
  auto holder =
      ctx_builder.InputTensors({(gert::Tensor *) &shape0, (gert::Tensor *) &shape0}).OutputShapes({&shape0}).Build();
  auto ctx = holder.GetContext();
  EXPECT_NE(ctx, nullptr);
  auto ctx_compute_node_info = ctx->GetComputeNodeInfo();
  EXPECT_NE(ctx_compute_node_info, nullptr);
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeType()), std::string("DIY"));
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeName()), std::string("diy_1"));
  EXPECT_EQ(ctx_compute_node_info->GetIrInputsNum(), 2);
  EXPECT_EQ(ctx_compute_node_info->GetIrOutputsNum(), 1);
  EXPECT_EQ(ctx_compute_node_info->GetInputsNum(), 2);
  EXPECT_EQ(ctx_compute_node_info->GetOutputsNum(), 1);
}

TEST_F(UtestContextBuilder, CreateInferShapeContextOK) {
  OpInferShapeContextBuilder ctx_builder;
  StorageShape shape0 = {{1, 2, 3, 4}, {4, 3, 2, 1}};
  StorageShape shape1 = {{2, 3, 4, 5}, {5, 4, 3, 2}};
  StorageShape shape2 = {{3, 4, 5, 6}, {6, 5, 4, 3}};
  StorageShape shape3 = {{4, 5, 6, 7}, {7, 6, 5, 4}};
  StorageShape outshape0 = {};
  StorageShape outshape1 = {};

  std::vector<gert::Tensor *> input_dtype_ref = {(gert::Tensor *) &shape0, (gert::Tensor *) &shape1,
                                                 (gert::Tensor *) &shape2, (gert::Tensor *) &shape3};
  std::vector<StorageShape *> output_dtype_ref = {&outshape0, &outshape1};
  ctx_builder.MutableOpInfo()
      .OpType("DIY")
      .OpName("diy_1")
      .IOInstanceNum({1, 1, 1, 1}, {2})
      .SetInputTd(0, ge::DT_FLOAT, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(1, ge::DT_FLOAT, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(2, ge::DT_FLOAT, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetInputTd(3, ge::DT_FLOAT, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetOutputTd(0, ge::DT_FLOAT, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND)
      .SetOutputTd(1, ge::DT_FLOAT, ge::FORMAT_FRACTAL_NZ, ge::FORMAT_ND);
  auto holder = ctx_builder.InputTensors(input_dtype_ref).OutputShapes(output_dtype_ref).Build();
  auto ctx = holder.GetContext();
  EXPECT_NE(ctx, nullptr);
  auto ctx_compute_node_info = ctx->GetComputeNodeInfo();
  EXPECT_NE(ctx_compute_node_info, nullptr);
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeType()), std::string("DIY"));
  EXPECT_EQ(std::string(ctx_compute_node_info->GetNodeName()), std::string("diy_1"));
  EXPECT_EQ(ctx_compute_node_info->GetIrInputsNum(), 4);
  EXPECT_EQ(ctx_compute_node_info->GetIrOutputsNum(), 2);
  EXPECT_EQ(ctx_compute_node_info->GetInputsNum(), 4);
  EXPECT_EQ(ctx_compute_node_info->GetOutputsNum(), 1);
  const CompileTimeTensorDesc *info_input_0 = ctx_compute_node_info->GetInputTdInfo(0);
  EXPECT_NE(info_input_0, nullptr);
  EXPECT_EQ(info_input_0->GetStorageFormat(), ge::FORMAT_ND);
  EXPECT_EQ(info_input_0->GetOriginFormat(), ge::FORMAT_FRACTAL_NZ);
  EXPECT_NE(ctx->GetInputShape(0), nullptr);
  EXPECT_EQ(*(ctx->GetInputShape(0)), shape0.GetOriginShape());
  EXPECT_NE(ctx->GetInputShape(1), nullptr);
  EXPECT_EQ(*(ctx->GetInputShape(1)), shape1.GetOriginShape());
  EXPECT_NE(ctx->GetInputShape(2), nullptr);
  EXPECT_EQ(*(ctx->GetInputShape(2)), shape2.GetOriginShape());
  EXPECT_NE(ctx->GetInputShape(3), nullptr);
  EXPECT_EQ(*(ctx->GetInputShape(3)), shape3.GetOriginShape());
  EXPECT_NE(ctx->GetOutputShape(0), nullptr);
  EXPECT_EQ(*(ctx->GetOutputShape(0)), outshape0.GetOriginShape());
  EXPECT_NE(ctx->GetOutputShape(1), nullptr);
  EXPECT_EQ(*(ctx->GetOutputShape(1)), outshape1.GetOriginShape());
}

TEST_F(UtestContextBuilder, CreateInferShapeRangeContextOK) {
  OpInferShapeRangeContextBuilder ctx_builder;
  gert::Shape xShapeMin{1, 1, 1, 1, 1};
  gert::Shape xShapeMax{10, 10, 10, 10, 20};
  gert::Shape wShapeMin{1, 1, 1, 1, 1};
  gert::Shape wShapeMax{10, 10, 10, 10, 20};
  gert::Shape yShapeMinNull{};
  gert::Shape yShapeMaxNull{};
  gert::Shape yShapeMin{1, 1, 1, 1, 1};
  gert::Shape yShapeMax{10, 10, 10, 10, 20};

  gert::Range<gert::Tensor> xShapeRange((gert::Tensor *)&xShapeMin, (gert::Tensor *)&xShapeMax);
  gert::Range<gert::Tensor> wShapeRange((gert::Tensor *)&wShapeMin, (gert::Tensor *)&wShapeMax);
  gert::Range<gert::Shape> yShapeRange(&yShapeMinNull, &yShapeMaxNull);

  ctx_builder.MutableOpInfo()
      .IONum(2, 1)
      .OpType("DIY")
      .OpName("diy_1")
      .SetInputTd(0, ge::DT_INT8, ge::Format::FORMAT_NCDHW, ge::Format::FORMAT_RESERVED)
      .SetInputTd(1, ge::DT_INT8, ge::Format::FORMAT_NCDHW, ge::Format::FORMAT_RESERVED)
      .SetOutputTd(0, ge::DT_FLOAT16, ge::Format::FORMAT_NCDHW, ge::Format::FORMAT_RESERVED);

  auto holder = ctx_builder.InputTensors({&xShapeRange, &wShapeRange}).OutputShapes({&yShapeRange}).Build();

  auto ctx = holder.GetContext();
  EXPECT_NE(ctx, nullptr);
  const CompileTimeTensorDesc *info_input_0 = ctx->GetInputDesc(0);
  EXPECT_NE(info_input_0, nullptr);
  EXPECT_EQ(info_input_0->GetDataType(), ge::DT_INT8);
  EXPECT_EQ(info_input_0->GetOriginFormat(), ge::FORMAT_NCDHW);
  EXPECT_EQ(info_input_0->GetStorageFormat(), ge::FORMAT_RESERVED);
  const CompileTimeTensorDesc *info_input_1 = ctx->GetInputDesc(1);
  EXPECT_NE(info_input_1, nullptr);
  EXPECT_EQ(info_input_1->GetDataType(), ge::DT_INT8);
  EXPECT_EQ(info_input_1->GetOriginFormat(), ge::FORMAT_NCDHW);
  EXPECT_EQ(info_input_1->GetStorageFormat(), ge::FORMAT_RESERVED);
  const CompileTimeTensorDesc *info_output_0 = ctx->GetOutputDesc(0);
  EXPECT_NE(info_output_0, nullptr);
  EXPECT_EQ(info_output_0->GetDataType(), ge::DT_FLOAT16);
  EXPECT_EQ(info_output_0->GetOriginFormat(), ge::FORMAT_NCDHW);
  EXPECT_EQ(info_output_0->GetStorageFormat(), ge::FORMAT_RESERVED);
  EXPECT_NE(ctx->GetInputShapeRange(0), nullptr);
  EXPECT_EQ(*(ctx->GetInputShapeRange(0)->GetMin()), xShapeMin);
  EXPECT_EQ(*(ctx->GetInputShapeRange(0)->GetMax()), xShapeMax);
  EXPECT_NE(ctx->GetInputShapeRange(1), nullptr);
  EXPECT_EQ(*(ctx->GetInputShapeRange(1)->GetMin()), wShapeMin);
  EXPECT_EQ(*(ctx->GetInputShapeRange(1)->GetMax()), wShapeMax);
  EXPECT_NE(ctx->GetOutputShapeRange(0), nullptr);
  EXPECT_EQ(*(ctx->GetOutputShapeRange(0)->GetMin()), yShapeMinNull);
  EXPECT_EQ(*(ctx->GetOutputShapeRange(0)->GetMax()), yShapeMinNull);
  ctx->GetOutputShapeRange(0)->GetMin()->SetDimNum(5);
  ctx->GetOutputShapeRange(0)->GetMax()->SetDimNum(5);
  for (size_t i = 0; i < 5; i++) {
    ctx->GetOutputShapeRange(0)->GetMin()->SetDim(i, yShapeMin[i]);
    ctx->GetOutputShapeRange(0)->GetMax()->SetDim(i, yShapeMax[i]);
  }
  EXPECT_EQ(*(ctx->GetOutputShapeRange(0)->GetMin()), yShapeMin);
  EXPECT_EQ(*(ctx->GetOutputShapeRange(0)->GetMax()), yShapeMax);
}

TEST_F(UtestContextBuilder, CreateTilingContextOK) {
  auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(4096);
  auto ws_ptr = reinterpret_cast<gert::ContinuousVector *>(workspace_size_holer.get());

  gert::Shape shape_0{1, 1, 1, 1, 1};
  gert::Shape shape_1{10, 10, 10, 10, 20};
  gert::Shape shape_2{1, 1, 1, 1, 1};
  gert::Shape shape_3{10, 10, 10, 10, 20};
  gert::Shape resultShape{10, 10, 10, 10, 20};

  gert::StorageShape x({1, 1, 1, 1, 1}, {1, 1, 1, 1, 1});
  gert::StorageShape resultIn({10, 10, 10, 10, 20}, {10, 10, 10, 10, 20});
  gert::StorageShape gamma({1, 1, 1, 1, 1}, {1, 1, 1, 1, 1});
  gert::StorageShape beta({10, 10, 10, 10, 20}, {10, 10, 10, 10, 20});
  gert::StorageShape result({10, 10, 10, 10, 20}, {10, 10, 10, 10, 20});

  uint8_t data_x[1] = {9};
  gert::Tensor x_tensor(x, {ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, ExpandDimsType()}, TensorPlacement::kOnHost, ge::DT_FLOAT, (void*)data_x);
  gert::Tensor resultIn_tensor(resultIn, {ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, ExpandDimsType()}, TensorPlacement::kOnHost, ge::DT_FLOAT, nullptr);
  gert::Tensor gammax_tensor(gamma, {ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, ExpandDimsType()}, TensorPlacement::kOnHost, ge::DT_FLOAT, nullptr);
  gert::Tensor beta_tensor(beta, {ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, ExpandDimsType()}, TensorPlacement::kOnHost, ge::DT_FLOAT, nullptr);
  gert::Tensor result_tensor(result, {ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, ExpandDimsType()}, TensorPlacement::kOnHost, ge::DT_FLOAT, nullptr);

  auto tmp_tiling_data = gert::TilingData::CreateCap(100);
  uint8_t tmp_compile_info[] = {1, 2, 3, 4, 5, 6, 7};
  uint8_t tmp_platform_info[] = {1, 2, 3, 4, 5, 6, 7};
  int32_t deterministic = 10;

  OpTilingContextBuilder ctx_builder;

  ctx_builder.MutableOpInfo()
      .OpName("tmp")
      .OpType("DIY")
      .IONum(4, 1)
      .SetInputTd(0, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, x)
      .SetInputTd(1, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, resultIn)
      .SetInputTd(2, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, gamma)
      .SetInputTd(3, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, beta)
      .SetOutputTd(0, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, result)
      .Attr(AscendString("axis"), int64_t(1))
      .Attr(AscendString("transpose"), bool(true))
      .Attr(AscendString("eps"), float(0.3))
      .Attr(AscendString("info"), AscendString("my_info"))
      .Attr(AscendString("bool_vec"), std::vector<bool>({true, false, true}))
      .Attr(AscendString("int_vec"), std::vector<int64_t>({1, 2, 3}))
      .Attr(AscendString("float_vec"), std::vector<float>({0.1, 0.2, 0.3}))
      .Attr(AscendString("str_vec"), std::vector<AscendString>({"123", "234"}))
      .Attr(AscendString("vec_vec_int"), std::vector<std::vector<int64_t>>({{1, 2, 3}, {4, 5, 6}}));

  auto holder = ctx_builder.TilingData((gert::TilingData *) tmp_tiling_data.get())
                    .Workspace(ws_ptr)
                    .CompileInfo(tmp_compile_info)
                    .Deterministic(deterministic)
                    .PlatformInfo(tmp_platform_info)
                    .InputTensors({&x_tensor, &resultIn_tensor, &gammax_tensor, &beta_tensor})
                    .OutputTensors({&result_tensor})
                    .Build();

  auto ctx = holder.GetContext();
  EXPECT_NE(ctx, nullptr);
  auto ctx_compute_node_info = ctx->GetComputeNodeInfo();
  EXPECT_NE(ctx_compute_node_info, nullptr);
  EXPECT_EQ(ctx->GetCompileInfo(), tmp_compile_info);
  EXPECT_EQ(ctx->GetInputShape(0)->GetOriginShape(), shape_0);
  EXPECT_EQ(ctx->GetInputShape(0)->GetStorageShape(), shape_0);
  EXPECT_EQ(ctx->GetInputTensor(0)->GetAddr(), data_x);
  EXPECT_EQ(ctx->GetInputTensor(0), &x_tensor);
  EXPECT_EQ(ctx->GetInputTensor(0)->GetStorageShape(), x_tensor.GetStorageShape());
  EXPECT_EQ(ctx->GetInputTensor(0)->GetOriginShape(), x_tensor.GetOriginShape());
  EXPECT_EQ(ctx->GetInputTensor(0)->GetSize(), x_tensor.GetSize());
  EXPECT_EQ(ctx->GetOutputShape(0)->GetOriginShape(), resultShape);
  EXPECT_EQ(ctx->GetOutputShape(0)->GetStorageShape(), resultShape);
  EXPECT_EQ((void *) (ctx->GetWorkspaceSizes(4096)), (void *) ws_ptr->GetData());
  EXPECT_EQ((void *) ctx->GetPlatformInfo(), (void *) tmp_platform_info);
  EXPECT_EQ(ctx->GetDeterministic(), deterministic);
  EXPECT_EQ((void *) ctx->GetRawTilingData(), (void *) tmp_tiling_data.get());
  EXPECT_EQ(*(ctx->GetAttrs()->GetInt(0)), 1);
  EXPECT_EQ(*(ctx->GetAttrs()->GetBool(1)), true);
  EXPECT_FLOAT_EQ(*(ctx->GetAttrs()->GetFloat(2)), 0.3);
  auto str_ptr = ctx->GetAttrs()->GetStr(3);
  EXPECT_EQ(strcmp(str_ptr, "my_info"), 0);
  auto bool_vec = ctx->GetAttrs()->GetAttrPointer<TypedContinuousVector<bool>>(4);
  EXPECT_EQ(bool_vec->GetData()[0], true);
  EXPECT_EQ(bool_vec->GetData()[1], false);
  EXPECT_EQ(bool_vec->GetData()[2], true);
  EXPECT_EQ(ctx->GetAttrs()->GetListInt(5)->GetData()[0], 1);
  EXPECT_EQ(ctx->GetAttrs()->GetListInt(5)->GetData()[1], 2);
  EXPECT_EQ(ctx->GetAttrs()->GetListInt(5)->GetData()[2], 3);
  EXPECT_FLOAT_EQ(ctx->GetAttrs()->GetListFloat(6)->GetData()[0], 0.1);
  EXPECT_FLOAT_EQ(ctx->GetAttrs()->GetListFloat(6)->GetData()[1], 0.2);
  EXPECT_FLOAT_EQ(ctx->GetAttrs()->GetListFloat(6)->GetData()[2], 0.3);
  auto int_vec_vec = ctx->GetAttrs()->GetListListInt(8);
  EXPECT_EQ(((int64_t *) (int_vec_vec->Get(0)->GetData()))[0], 1);
  EXPECT_EQ(((int64_t *) (int_vec_vec->Get(0)->GetData()))[1], 2);
  EXPECT_EQ(((int64_t *) (int_vec_vec->Get(0)->GetData()))[2], 3);
  EXPECT_EQ(((int64_t *) (int_vec_vec->Get(1)->GetData()))[0], 4);
  EXPECT_EQ(((int64_t *) (int_vec_vec->Get(1)->GetData()))[1], 5);
  EXPECT_EQ(((int64_t *) (int_vec_vec->Get(1)->GetData()))[2], 6);
}

TEST_F(UtestContextBuilder, CreateTilingParseContextOK) {

  gert::Shape shape_0{1, 1, 1, 1, 1};
  gert::Shape shape_1{10, 10, 10, 10, 20};
  gert::Shape shape_2{1, 1, 1, 1, 1};
  gert::Shape shape_3{10, 10, 10, 10, 20};
  gert::Shape resultShape{10, 10, 10, 10, 20};

  gert::StorageShape x({1, 1, 1, 1, 1}, {1, 1, 1, 1, 1});
  gert::StorageShape resultIn({10, 10, 10, 10, 20}, {10, 10, 10, 10, 20});
  gert::StorageShape gamma({1, 1, 1, 1, 1}, {1, 1, 1, 1, 1});
  gert::StorageShape beta({10, 10, 10, 10, 20}, {10, 10, 10, 10, 20});
  gert::StorageShape result({10, 10, 10, 10, 20}, {10, 10, 10, 10, 20});

  std::string tmp_compile_json = "123.json";

  uint8_t tmp_platform_info[] = {1, 2, 3, 4, 5, 6, 7};
  uint8_t tmp_compile_info[] = {1, 2, 3, 4, 5, 6, 7};

  OpTilingParseContextBuilder ctx_builder;

  ctx_builder.MutableOpInfo()
      .OpName("tmp")
      .OpType("DIY")
      .IONum(4, 1)
      .SetInputTd(0, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, x)
      .SetInputTd(1, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, resultIn)
      .SetInputTd(2, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, gamma)
      .SetInputTd(3, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, beta)
      .SetOutputTd(0, ge::DT_FLOAT, ge::FORMAT_NCDHW, ge::FORMAT_RESERVED, result);

  auto holder = ctx_builder.CompiledJson(tmp_compile_json.c_str())
                    .CompileInfo(tmp_compile_info)
                    .PlatformInfo(tmp_platform_info)
                    .Build();

  auto ctx = holder.GetContext();
  EXPECT_NE(ctx, nullptr);
  auto ctx_compute_node_info = ctx->GetComputeNodeInfo();
  EXPECT_NE(ctx_compute_node_info, nullptr);
  EXPECT_EQ(ctx->GetInputDesc(0)->GetOriginFormat(), ge::FORMAT_NCDHW);
  EXPECT_EQ(ctx->GetInputDesc(0)->GetStorageFormat(), ge::FORMAT_RESERVED);
  EXPECT_EQ((void *) ctx->GetPlatformInfo(), (void *) tmp_platform_info);
  EXPECT_EQ((void *) ctx->GetPlatformInfo(), (void *) tmp_platform_info);
  EXPECT_EQ(ctx->GetCompiledJson(), tmp_compile_json.c_str());
  EXPECT_EQ(ctx->GetCompiledInfo<uint8_t>(), tmp_compile_info);
}
